#include "ConfigManager.hpp"

ConfigNode::ConfigNode(const ConfigNode & node)
{
	m_value = node.m_value;
	m_config = node.m_config;
}

ConfigNode::ConfigNode(const String &value)
	: m_value(value)
{ }

ConfigNode::ConfigNode(ConfigNode && other) noexcept
	: m_value(std::move(other.m_value))
	, m_config(std::move(other.m_config))
{ }

ConfigNode &ConfigNode::operator[](const String &key)
{
	if(m_config.find(key) == m_config.end())
	{
		m_config[key] = ConfigNode();
	}
	return m_config[key];
}

ConfigNode &ConfigNode::operator=(const String &value)
{
	m_value = value;
	return *this;
}

ConfigNode &ConfigNode::operator=(const double &value)
{
	m_value = String::format("%f", value);
	return *this;
}

ConfigNode &ConfigNode::operator=(const long &value)
{
	m_value = String::format("%ld", value);
	return *this;
}

ConfigNode &ConfigNode::operator=(const ConfigNode & value)
{
	m_value = value.m_value;
	m_config = value.m_config;
	return *this;
}

ConfigNode &ConfigNode::operator=(ConfigNode && other) noexcept
{
	if(this != &other)
	{
		m_value = std::move(other.m_value);
		m_config = std::move(other.m_config);
	}
	return *this;
}

size_t ConfigNode::erase(const String &key)
{
	return m_config.erase(key);
}

size_t ConfigNode::remove(const String &key)
{
	return erase(key);
}

ConfigNode &ConfigNode::add(const String &key, const ConfigNode & value)
{
	m_config[key] = value;
	return *this;
}

ConfigNode &ConfigNode::add(const String &key, const String &value)
{
	m_config[key] = value;
	return *this;
}

std::vector<String> ConfigNode::keys() const
{
	std::vector<String> keys;
	for(auto &it : m_config)
	{
		keys.push_back(it.first);
	}
	return keys;
}

ConfigNode::ConfigConstIterator ConfigNode::find(const String &key) const
{
	return m_config.find(key);
}

ConfigNode::ConfigConstIterator ConfigNode::end() const
{
	return m_config.end();
}

ConfigParser::ConfigParser(const String &filePath)
{
	m_filePath = filePath;
}

bool ConfigParser::save(const String &filePath)
{
	String path = filePath;

	if(path.empty())
	{
		throw ConfigException("No file path specified for saving.");
	}

	std::ofstream file(path);
	if(!file.is_open())
	{
		std::cerr << "Error: Could not open file for writing: " << path << std::endl;
		return false;
	}

	file << toString();

	file.close();
	return true;
}

bool ConfigParser::save()
{
	return save(m_filePath);
}

std::vector<String> ConfigParser::sections() const
{
	std::vector<String> sections;
	for(auto &section : m_config)
	{
		sections.push_back(section.first);
	}
	return sections;
}

std::vector<String> ConfigParser::keys(const String &section) const
{
	return m_config.at(section).keys();
}

ConfigNode ConfigParser::section(const String &section) const
{
	return m_config.at(section);
}

bool ConfigParser::has(const String &section) const
{
	return m_config.find(section) != m_config.end();
}

bool ConfigParser::has(const String &section, const String &key) const
{
	const auto section_it = m_config.find(section);
	if(section_it != m_config.end())
	{
		return section_it->second.find(key) != section_it->second.end();
	}
	return false;
}

void ConfigParser::remove(const String &section)
{
	m_config.erase(section);
}

void ConfigParser::remove(const String &section, const String &key)
{
	m_config[section].erase(key);
}

String ConfigParser::trim(const String &str)
{
	const auto strBegin = str.find_first_not_of(" \t");
	if(strBegin == String::npos)
	{
		return "";    // no content
	}

	const auto strEnd = str.find_last_not_of(" \t");

	return str.substr(strBegin, strEnd - strBegin + 1);
}

ConfigNode &ConfigParser::operator[](const String &section)
{
	return m_config[section];
}

bool IniParser::load(const String &filePath)
{
	m_filePath = filePath;
	m_config.clear();

	std::ifstream file(filePath);
	if(!file.is_open())
	{
		std::cerr << "Error: Could not open config file: " << filePath << std::endl;
		return false;
	}

	String line;
	String currentSection;
	int lineNumber = 0;

	while(std::getline(file, line))
	{
		lineNumber++;
		// 去除行首尾空白
		line = trim(line);

		// 跳过空行和注释行
		if(line.empty() || line[0] == '#' || line[0] == ';')
		{
			continue;
		}

		// 检查是否为节头 [SectionName]
		if(line.front() == '[' && line.back() == ']')
		{
			currentSection = line.substr(1, line.length() - 2);
			// 确保节存在，即使它是空的
			m_config[currentSection];
		}
		else
		{
			// 解析键值对 key = value
			parseLine(line, currentSection, lineNumber);
		}
	}

	file.close();
	return true;
}

String IniParser::toString()
{
	String result;
	const auto top_section = sections();
	for(const auto& section : top_section)
	{
		result += "[" + section + "]\n";
		auto next_sections = keys(section);
		for(const auto& next_section : next_sections)
		{
			result += next_section + " = " + m_config[section][next_section].to<String>() + "\n";
		}
		result += "\n"; // 在节之间添加空行以提高可读性
	}
	return result;
}

void IniParser::parseLine(const String &line, const String &currentSection, int lineNumber)
{
	size_t eqPos = line.find('=');
	if(eqPos != std::string::npos)
	{
		std::string key = trim(line.substr(0, eqPos));
		std::string value = trim(line.substr(eqPos + 1));
		if(!currentSection.empty())
		{
			if(!has(currentSection))
			{
				m_config[currentSection] = ConfigNode();
			}
			m_config[currentSection][key] = value;
		}
		else
		{
			throw ConfigException("No section specified for key '" + key + "' at line " + std::to_string(lineNumber) + ".");
		}
	}
	else
	{
		throw ConfigException("No key specified at line " + std::to_string(lineNumber) + ".");
	}
}

bool JsonParser::load(const String &filePath)
{
	return false;
}

String JsonParser::toString()
{
	return String();
}

bool XmlParser::load(const String &filePath)
{
	return false;
}

String XmlParser::toString()
{
	return String();
}


ConfigManager::ConfigManager(const String &filePath)
{
	load(filePath);
}

bool ConfigManager::load(const String &filePath)
{
	std::lock_guard<std::mutex> lock(m_mutex);
	String file_type = filePath.subAfter('.').lower();
	if(file_type == "json")
	{
		m_configParser.reset(new JsonParser());
	}
	else if(file_type == "xml")
	{
		m_configParser.reset(new XmlParser());
	}
	else
	{
		m_configParser.reset(new IniParser());
	}
	return m_configParser.get()->load(filePath);
}

bool ConfigManager::save()
{
	std::lock_guard<std::mutex> lock(m_mutex);
	return m_configParser.get()->save();
}

bool ConfigManager::save(const String &filePath)
{
	std::lock_guard<std::mutex> lock(m_mutex);
	return m_configParser.get()->save(filePath);
}

std::vector<String> ConfigManager::sections()
{
	std::lock_guard<std::mutex> lock(m_mutex);
	return m_configParser.get()->sections();
}

std::vector<String> ConfigManager::keys(const String &section)
{
	std::lock_guard<std::mutex> lock(m_mutex);
	return m_configParser.get()->keys(section);
}

bool ConfigManager::has(const std::string & section) const
{
	std::lock_guard<std::mutex> lock(m_mutex);
	return m_configParser.get()->has(section);
}

bool ConfigManager::has(const std::string & section, const std::string & key) const
{
	std::lock_guard<std::mutex> lock(m_mutex);
	return m_configParser.get()->has(section, key);
}

ConfigNode &ConfigManager::operator[](const String &section)
{
	std::lock_guard<std::mutex> lock(m_mutex);
	return m_configParser.get()->operator[](section);
}

String ConfigManager::toString() const
{
	std::lock_guard<std::mutex> lock(m_mutex);
	return m_configParser.get()->toString();
}